// mdfu.h
#ifndef MDFU_H
#define MDFU_H

#include <vector>
#include <cstdint>
#include <string>
#include <cstdint> // 为了使用固定宽度的整数类型

enum class MdfuStatus
{
    SUCCESS = 1,
    COMMAND_NOT_SUPPORTED = 2,
    NOT_AUTHORIZED = 3,
    COMMAND_NOT_EXECUTED = 4,
    ABORT_FILE_TRANSFER = 5
};

enum class MdfuCmd
{
    GET_CLIENT_INFO = 1,
    START_TRANSFER = 2,
    WRITE_CHUNK = 3,
    GET_IMAGE_STATE = 4,
    END_TRANSFER = 5
};

enum class ClientInfoType
{
    PROTOCOL_VERSION = 1,
    BUFFER_INFO = 2,
    COMMAND_TIMEOUTS = 3,
    INTER_TRANSACTION_DELAY = 4
};

enum class ImageState
{
    VALID = 1,
    INVALID = 2
};

class MdfuStatusPacket
{
public:
    MdfuStatusPacket(){}
    MdfuStatusPacket(int sequence_number, int status, const std::vector<uint8_t> &data, bool resend = false);
    std::string to_string() const;
    static MdfuStatusPacket from_binary(const std::vector<uint8_t> &packet);
    std::vector<uint8_t> to_binary() const;

// private:
    int sequence_number;
    int status;
    std::vector<uint8_t> data;
    bool resend;

    static std::tuple<int, int, std::vector<uint8_t>, bool> decode_packet(const std::vector<uint8_t> &packet);
};

// TODO 是否需要一个Transport实例对象？？？
class Mdfu
{
public:
    Mdfu(); // 默认构造函数
    Mdfu(int init_retries, std::string init_device_port);
    ~Mdfu(); // 析构函数

    // 成员函数
    void run_upgrade(const std::vector<uint8_t> &image);     
    void get_client_info();                                                       // 执行固件升级
    void start_transfer(bool sync = false);                                                                      // 开始传输命令
    void end_transfer(); 
    uint8_t get_image_state();                                                                                   //                                                                                         // 结束传输命令
    void write_chunk(const std::vector<uint8_t> &chunk);                                                            // 写入一个数据块
    std::vector<std::vector<uint8_t>> chunkify(const std::vector<uint8_t> &data, size_t chunk_size, int padding = -1); // 将数据分块
    MdfuStatusPacket send_cmd(MdfuCmd command, const std::vector<uint8_t>& data = {}, bool sync = false);           // 发送命令
    void _increment_sequence_number();                                                                           // 自增序列号

    static std::string testJni();
    static std::string testFrameData();
    std::vector<uint8_t> test_send_cmd(MdfuCmd command, const std::vector<uint8_t>& data = {}, bool sync = false); // 测试发送命令

private:

    // 成员变量
    int retries;             // 重试次数
    std::string device_port; // 设备端口
    int sequence_number;     // 成员变量，用于存储序列号
};

class MdfuCmdPacket
{
public:
    MdfuCmdPacket(int sequence_number, MdfuCmd command, const std::vector<uint8_t> &data, bool sync = false);
    std::vector<uint8_t> to_binary(); // 转换为二进制数据
    std::string to_string() const;

private:
    bool sync;
    MdfuCmd command;
    std::vector<uint8_t> data;
    int sequence_number;
};

#endif // MDFU_H
